package ar.com.pragmatia.lanacion.data;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;
import ar.com.pragmatia.lanacion.app.App;
import ar.com.pragmatia.lanacion.utils.Strings;

public class Syncronizer {

	// private final static String BASE_URI = "http://192.168.1.100/";
	private final static String BASE_URI = "http://pragmatia.com.ar/";
	private final static String EXPORT_URL = BASE_URI
			+ "lanacion/tables/export";

	private final static String SYNCURL = BASE_URI + "lanacion/tables/";
	private final static String CLIENTS_IMG_URL = BASE_URI
			+ "lanacion/clients/upload_client_pictures";
	private final static String VISITS_IMG_URL = BASE_URI
			+ "lanacion/visits/upload_visit_pictures";
	private final static String loginUrl = BASE_URI + "lanacion/users/login";

	public static void sync() {
		Syncronizer.sync("");
	}

	private static boolean syncVisits() {
		Visit visit = new Visit();
		Vector<AppData> vec = visit.find("WHERE sent = 'false'");
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(10);
		if (vec.size() > 0) {
			for (int i = 0; i < vec.size(); i++) {
				Visit visi = (Visit) vec.get(i);
				nameValuePairs.add(new BasicNameValuePair("data[Visits][" + i
						+ "][Visit][id]", visi.getId()));
				nameValuePairs.add(new BasicNameValuePair("data[Visits][" + i
						+ "][Visit][client_id]", visi.getClientId()));
				nameValuePairs.add(new BasicNameValuePair("data[Visits][" + i
						+ "][Visit][contact]", visi.getContact()));
				nameValuePairs.add(new BasicNameValuePair("data[Visits][" + i
						+ "][Visit][reason]", visi.getReason()));
				nameValuePairs.add(new BasicNameValuePair("data[Visits][" + i
						+ "][Visit][result]", visi.getResult()));
				nameValuePairs.add(new BasicNameValuePair("data[Visits][" + i
						+ "][Visit][claim]", visi.getClaim()));
				nameValuePairs.add(new BasicNameValuePair("data[Visits][" + i
						+ "][Visit][location]", visi.getLocation()));
				nameValuePairs
						.add(new BasicNameValuePair("data[Visits][" + i
								+ "][Visit][items_delivered]", visi
								.getItemsDelivered()));
				nameValuePairs.add(new BasicNameValuePair("data[Visits][" + i
						+ "][Visit][observations]", visi.getObservations()));
				nameValuePairs.add(new BasicNameValuePair("data[Visits][" + i
						+ "][Visit][date]", visi.getDate()));
				nameValuePairs
						.add(new BasicNameValuePair("data[Visits][" + i
								+ "][Visit][next_visit_date]", visi
								.getNextVisitDate()));
			}
			try {
				String response = getStringFromRequest(doPostRequest(SYNCURL
						+ "sync_visits", nameValuePairs));

				App.log("asd", "asd", response);
				JSONObject jObj = new JSONObject(response);

				JSONArray added = jObj.getJSONArray("added");
				JSONArray array = jObj.getJSONArray("delete");

				if (added.length() == array.length()) {
					for (int i = 0; i < array.length(); i++) {

						Visit cli = new Visit();

						cli = (Visit) cli.find(
								"WHERE id = '" + array.get(i) + "'").get(0);

						App.log("asd", "asd", cli.toString());

						if ((new File("/sdcard/LaNacion/Visit/" + cli.getUuid()
								+ ".jpg")).exists()) {
							HttpFileUploader htfu = new HttpFileUploader(
									VISITS_IMG_URL);
							// TEXT
							BasicNameValuePair newVar = new BasicNameValuePair(
									"data[Visit][id]", added.get(i).toString());
							htfu.addVar(newVar);

							newVar = new BasicNameValuePair(
									"data[User][devId]", App.getDeviceId());
							htfu.addVar(newVar);

							// FILE asdasdasd

							htfu.addFile(
									"/sdcard/LaNacion/Visit/" + cli.getUuid()
											+ ".jpg", "multa.jpg",
									"data[Visit][picture]");

							htfu.excecute();

							JSONObject jsonResponse = new JSONObject(
									htfu.getResponseMessage());
							boolean uploaded = jsonResponse.getBoolean("saved");
							if (uploaded) {
								new File("/sdcard/LaNacion/Visit/"
										+ cli.getUuid() + ".jpg").delete();
							}
						}
						App.getDb().delete("visits",
								"id = '" + array.get(i) + "'", null);
						// App.getDb().delete("order_details",
						// "order_id = '" + array.get(i) + "'", null);
					}

				}

				// JSONArray array = new JSONArray(response);
				// for (int i = 0; i < array.length(); i++) {
				// App.getDb().delete("visits", "id = '" + array.get(i) + "'",
				// null);
				// }
				return true;
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (IllegalStateException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		return false;
	}

	private static boolean syncPendingClients() {
		PendingClient visit = new PendingClient();
		Vector<AppData> vec = visit.find();
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(10);
		if (vec.size() > 0) {
			for (int i = 0; i < vec.size(); i++) {
				PendingClient visi = (PendingClient) vec.get(i);
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][id]", visi.getId()));
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][shop_name]", visi.getShopName()));
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][business_name]", visi.getBusinessName()));
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][client_name]", visi.getClientName()));
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][telephone]", visi.getTelephone()));
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][legal_certificate]", visi
						.getLegalCertificate()));
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][address]", visi.getAddress()));
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][location]", visi.getLocation()));
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][prices]", visi.getPrices()));
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][city]", visi.getCity()));
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][state]", visi.getState()));
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][giro]", visi.getGiro()));
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][registry_number]", visi
						.getRegistryNumber()));
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][authorized_signer]", visi
						.getAuthorizedSigner()));
				nameValuePairs.add(new BasicNameValuePair("data[Clients][" + i
						+ "][Client][authorized_signer_id_card]", visi
						.getAuthorizedSignerIdCard()));
			}
			try {

				String response = getStringFromRequest(doPostRequest(SYNCURL
						+ "sync_clients", nameValuePairs));

				JSONObject jObj = new JSONObject(response);

				JSONArray added = jObj.getJSONArray("added");
				JSONArray array = jObj.getJSONArray("delete");

				if (added.length() == array.length()) {
					for (int i = 0; i < array.length(); i++) {

						PendingClient cli = new PendingClient();

						cli = (PendingClient) cli.find(
								"WHERE id = '" + array.get(i) + "'").get(0);

						if ((new File("/sdcard/LaNacion/Client/"
								+ cli.getUuid() + ".jpg")).exists()) {

							HttpFileUploader htfu = new HttpFileUploader(
									CLIENTS_IMG_URL);
							// TEXT
							BasicNameValuePair newVar = new BasicNameValuePair(
									"data[Client][id]", added.get(i).toString());
							htfu.addVar(newVar);

							newVar = new BasicNameValuePair(
									"data[User][devId]", App.getDeviceId());
							htfu.addVar(newVar);

							// FILE asdasdasd
							htfu.addFile(
									"/sdcard/LaNacion/Client/" + cli.getUuid()
											+ ".jpg", "multa.jpg",
									"data[Client][picture]");

							htfu.excecute();

							JSONObject jsonResponse = new JSONObject(
									htfu.getResponseMessage());
							boolean uploaded = jsonResponse.getBoolean("saved");
							if (uploaded) {
								new File("/sdcard/LaNacion/Client/"
										+ cli.getUuid() + ".jpg").delete();
							}
						}
						App.getDb().delete("pending_clients",
								"id = '" + array.get(i) + "'", null);
						// App.getDb().delete("order_details",
						// "order_id = '" + array.get(i) + "'", null);
					}
					return true;
				}
			} catch (ClientProtocolException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} catch (IllegalStateException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		return false;
	}

	private static boolean syncOrders() {
		Order order = new Order();
		Vector<AppData> vec = order.find("WHERE sent = 'false'");
		List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(10);
		if (vec.size() > 0) {
			for (int i = 0; i < vec.size(); i++) {
				Order visi = (Order) vec.get(i);
				nameValuePairs.add(new BasicNameValuePair("data[Orders][" + i
						+ "][Order][id]", visi.getId()));
				nameValuePairs.add(new BasicNameValuePair("data[Orders][" + i
						+ "][Order][location]", visi.getLocation()));
				nameValuePairs.add(new BasicNameValuePair("data[Orders][" + i
						+ "][Order][order_type]", visi.getOrderType()));
				nameValuePairs.add(new BasicNameValuePair("data[Orders][" + i
						+ "][Order][document_type]", visi.getDocumentType()));
				nameValuePairs.add(new BasicNameValuePair("data[Orders][" + i
						+ "][Order][client_id]", visi.getClientId()));

				Vector<AppData> vtr = visi.getOrderDetail();
				for (int j = 0; j < vtr.size(); j++) {
					OrderDetail detail = (OrderDetail) vtr.get(j);

					nameValuePairs.add(new BasicNameValuePair("data[Orders]["
							+ i + "][OrderDetails][" + j
							+ "][OrderDetail][article_id]", detail
							.getArticleId()));
					nameValuePairs
							.add(new BasicNameValuePair("data[Orders][" + i
									+ "][OrderDetails][" + j
									+ "][OrderDetail][quantity]", detail
									.getQuantity()));
					nameValuePairs.add(new BasicNameValuePair("data[Orders]["
							+ i + "][OrderDetails][" + j
							+ "][OrderDetail][price]", detail.getPrice()));
				}

			}

			try {
				String response = getStringFromRequest(doPostRequest(SYNCURL
						+ "sync_orders", nameValuePairs));

				JSONArray array = new JSONArray(response);
				for (int i = 0; i < array.length(); i++) {
					App.getDb().delete("orders", "id = '" + array.get(i) + "'",
							null);
					App.getDb().delete("order_details",
							"order_id = '" + array.get(i) + "'", null);
				}
				return true;
			} catch (ClientProtocolException e) {
			} catch (IOException e) {
			} catch (IllegalStateException e) {
				e.printStackTrace();
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		return false;
	}

	public static void sync(String extra) {

		StringBuilder sbUrl = new StringBuilder();
		sbUrl.append(EXPORT_URL);
		User user = App.getUser();
		syncVisits();
		syncPendingClients();
		syncOrders();
		// sbUrl.append("service=sync");

		// if (extra != null && !extra.equals("")) {
		// sbUrl.append("&" + extra);
		// }

		// if (!App.getAccount().isEmpty()) {

		// sbUrl.append("&g=");
		// sbUrl.append(App.getDeviceId());

		// JSONArray jsonArray = new JSONArray();

		// String sql =
		// "SELECT id, viewed_date, viewed_time FROM ads WHERE state LIKE 'pending' AND (type LIKE 'PUSH' OR type LIKE 'STD')";
		// Cursor ads = App.getDataHelper().getDb().rawQuery(sql, null);

		// if (ads.getCount() > 0) {
		//
		// ads.moveToFirst();
		//
		// while (ads.isAfterLast() == false) {
		//
		// try {
		// jsonArray
		// .put(new JSONObject()
		// .put("id",
		// Strings.addToJson(ads.getString(ads
		// .getColumnIndex("id"))))
		// .put("viewed_time",
		// Strings.addToJson(ads.getString(ads
		// .getColumnIndex("viewed_time"))))
		// .put("viewed_date",
		// Strings.addToJson(ads.getString(ads
		// .getColumnIndex("viewed_date")))));
		// } catch (JSONException e) {
		// App.log("Syncronizer", "sync", e.getMessage());
		// }
		//
		// ads.moveToNext();
		// }
		//
		// JSONObject jsonObject = new JSONObject();
		// try {
		// jsonObject.put("Ads", jsonArray);
		// } catch (JSONException e) {
		// App.log("Syncronizer", "sync", e.getMessage());
		// }
		//
		// // add to the request
		// sbUrl.append("&d=");
		// sbUrl.append(Syncronizer.encode(jsonObject.toString()));
		//
		// }
		// ads.close();
		// }

		String dt = "";
		if (!Strings.isNullOrEmpty(user.getLastLogin())) {
			dt = "/date:" + user.getLastLogin();
		}

		App.log("Asd", "asdasd", sbUrl.toString() + dt);

		String jsonText = executeHttpGet(sbUrl.toString() + dt);

		Syncronizer.processResponse(jsonText);

	}

	public static String processResponse(String jsonText) {

		// App.log("Syncronizer", "sync", jsonText);

		StringBuilder sb = new StringBuilder();

		try {

			JSONObject objects = new JSONObject(jsonText);

			// If response, means that the be has the updated info, so I can
			// delete my ads only if new ads are coming
			// if (objects.has("Response")) {
			// if (objects.has("Ads")) {
			// Account account = App.getAccount();
			// account.setLastUpdate(Format.getFrenchDate());
			// account.save();
			//
			// App.getDb().execSQL("DELETE FROM ads");
			// } else {
			// App.getDb()
			// .execSQL(
			// "UPDATE ads SET state = 'send' WHERE state LIKE 'pending'");
			// }
			// }

			@SuppressWarnings("unchecked")
			Iterator<String> iterator = objects.keys();

			while (iterator.hasNext()) {

				String key = iterator.next();

				JSONArray records = objects.getJSONArray(key);

				if (!key.equals("Errors") && !key.equals("Response")) {
					// App.log("AppActivity", "load", key);
					AppData entity = DataFactory.getClass(key);
					if (entity.loadAndSave(records)) {
						App.log("Es", "un", "Fucking test");
						SimpleDateFormat sdf = new SimpleDateFormat(
								"yyyy-MM-dd_HH:mm");
						User user = App.getUser();
						user.setLastLogin(sdf.format(new Date()));
						user.save();
					}

				} else {

					if (key.equals("Errors")) {
						try {
							for (int i = 0; i < records.length(); i++) {

								JSONObject responseObject = records
										.getJSONObject(i);

								sb.append("(" + responseObject.get("code")
										+ ")");
								sb.append(" " + responseObject.get("message"));
								sb.append("\n");

							}
						} catch (JSONException e) {
							App.log("AppActivity", "load", e.getMessage());
						}
					}
				}
			}

		} catch (JSONException e) {
			e.printStackTrace();
			App.log("Syncronizer", "sync", e.getMessage());
		}

		return sb.toString();
	}

	public static boolean logIn(String username, String password) {
		try {
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(3);
			nameValuePairs.add(new BasicNameValuePair("data[User][username]",
					username));
			nameValuePairs.add(new BasicNameValuePair("data[User][password]",
					password));
			String response = getStringFromRequest(doPostRequest(loginUrl,
					nameValuePairs));
			App.log("Syncronizer", "logIn", response);
			JSONObject userJson = new JSONObject(response);
			User user = new User(userJson);
			user.save(true);
			App.setUser(user);
			return true;
		} catch (ClientProtocolException e) {
			Log.d("Parquimetros", e.toString());
		} catch (IOException e) {
			Log.d("Parquimetros", e.toString());
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return false;
	}

	protected static HttpResponse doPostRequest(String url,
			List<NameValuePair> nameValuePairs) throws ClientProtocolException,
			IOException {
		HttpClient httpclient = new DefaultHttpClient();
		HttpPost httppost = new HttpPost(url);
		if (App.getDeviceId() != null) {
			nameValuePairs.add(new BasicNameValuePair("data[User][devId]", App
					.getDeviceId()));
		}
		httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
		HttpResponse rtrn = httpclient.execute(httppost);
		return rtrn;

	}

	protected static String getStringFromRequest(HttpResponse response)
			throws IllegalStateException, IOException {
		BufferedReader in;
		HttpEntity entity = response.getEntity();
		in = new BufferedReader(new InputStreamReader(entity.getContent()));
		StringBuffer sb = new StringBuffer("");
		String line = "";
		while ((line = in.readLine()) != null) {
			sb.append(line);
		}
		in.close();
		return sb.toString();
	}

	public static String executeHttpGet(String url) {
		if (App.getDeviceId() != null) {
			url += "/devId:" + App.getDeviceId();
		}
		App.log("Syncronizer", "executeHttpGet", url);
		BufferedReader in = null;
		StringBuffer sb = new StringBuffer("");
		try {
			HttpClient client = new DefaultHttpClient();
			HttpGet request = new HttpGet(url);
			// request.setURI(new URI(url));
			HttpResponse response = client.execute(request);
			in = new BufferedReader(new InputStreamReader(response.getEntity()
					.getContent()));

			String line = "";
			while ((line = in.readLine()) != null) {
				sb.append(line);
			}
			in.close();
		} catch (Exception e) {
			e.printStackTrace();
			App.log("Syncronizer", "executeHttpGet", e.getMessage());
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

		return sb.toString();
	}

}
